<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Repositories\TransactionRepository;
use Illuminate\Http\Request;
use App\Http\Model\StockFinancing;
use App\Http\Model\StockFinanceEntrust;

class TransactionController extends Controller
{
    private $transaction = null;
    const JAVA_URL = JAVA_API_URL;
    const ENTRUST_BUY_URL = self::JAVA_URL . "/entrust/api/1.0/entrustBuy";
    const ENTRUST_SELL_URL = self::JAVA_URL . "/entrust/api/1.0/entrustSell";
    const CANCEL_ENTRUST_BUY_URL = self::JAVA_URL . "/entrust/api/1.0/cancelEntrustBuy";
    const CANCEL_ENTRUST_CELL_URL = self::JAVA_URL . "/entrust/api/1.0/cancelEntrustSell";

    public function __construct(TransactionRepository $transaction)
    {
        $this->middleware(["auth:api", "App\Http\Middleware\UserForbidden"]);
        $this->transaction = $transaction;
    }

    /**
     * 委托买入
     */
    public function entrustBuy(Request $request)
    {
        $user = $request->user();
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1",
            "price_type" => "required|integer|between:1,2",
            "stock_code" => "required|min:1",
            "entrust_quantity" => "required|numeric|min:100",
        ], [
            "id.required" => "配资信息错误",
            "id.integer" => "配资信息错误",
            "id.min" => "配资信息错误",
            "stock_code.min" => "请填写正确的证券代码",
            "stock_code.required" => "请填写正确的证券代码",
            "entrust_quantity.required" => "请填写正确的买入数量",
            "entrust_quantity.numeric" => "请填写正确的买入数量",
            "entrust_quantity.min" => "买入数量不能少于100",
            "price_type.required" => "买入方式错误",
            "price_type.integer" => "买入方式错误",
            "price_type.between" => "买入方式错误",
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        if ($request->get("price_type") == 1) {
            $entrust_price = $request->get("entrust_price");
            if (!$entrust_price || $entrust_price <= 0) {
                return parent::jsonReturn([], parent::CODE_FAIL, "请填写正确的委托价格");
            }
        }

        if ($request->get("entrust_quantity") % 100 != 0) {
            return parent::jsonReturn([], parent::CODE_FAIL, "买入数量应该为100的整倍数");
        }

        if (!StockFinancing::where("cust_id", $user->id)->where("id", $request->get("id"))->count()) {
            return parent::jsonReturn([], parent::CODE_FAIL, "用户配资错误");
        }

        $data = [
            "custId" => $user->id,
            "entrustIp" => $request->ip(),
            "entrustSource" => "电脑网页",
            "entrustPrice" => $request->get("entrust_price"),
            "entrustQuantity" => $request->get("entrust_quantity"),
            "priceType" => $request->get("price_type"),
            "sellBuy" => 1,
            "stockCode" => $request->get("stock_code"),
            "stockFinanceId" => $request->get("id"),
        ];
        $ret = requestJava(self::ENTRUST_BUY_URL, [], $data);
        return isset($ret["code"]) && $ret["code"] ? parent::jsonReturn([], parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $ret["msg"] ?: "委托失败");
    }

    /**
     * 委托卖出
     */
    public function entrustCell(Request $request)
    {
        $user = $request->user();
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1",
            "price_type" => "required|integer|between:1,2",
            "stock_code" => "required|min:1",
            "entrust_quantity" => "required|numeric",
            "parent_stock_finance_id" => "required|integer|min:1",
        ], [
            "id.required" => "配资信息错误",
            "id.integer" => "配资信息错误",
            "id.min" => "配资信息错误",
            "parent_stock_finance_id.required" => "委托信息错误",
            "parent_stock_finance_id.integer" => "委托信息错误",
            "parent_stock_finance_id.min" => "委托信息错误",
            "stock_code.min" => "请填写正确的证券代码",
            "stock_code.required" => "请填写正确的证券代码",
            "entrust_quantity.required" => "请填写正确的卖出数量",
            "entrust_quantity.numeric" => "请填写正确的卖出数量",
            "price_type.required" => "卖出方式错误",
            "price_type.integer" => "卖出方式错误",
            "price_type.between" => "卖出方式错误",
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        if ($request->get("price_type") == 1) {
            $entrust_price = $request->get("entrust_price");
            if (!$entrust_price || $entrust_price <= 0) {
                return parent::jsonReturn([], parent::CODE_FAIL, "请填写正确的委托价格");
            }
        }

        if (!StockFinancing::where("cust_id", $user->id)->where("id", $request->get("id"))->count()) {
            return parent::jsonReturn([], parent::CODE_FAIL, "用户配资错误");
        }

        $data = [
            "custId" => $user->id,
            "entrustIp" => $request->ip(),
            "entrustSource" => "电脑网页",
            "entrustPrice" => $request->get("entrust_price"),
            "entrustQuantity" => $request->get("entrust_quantity"),
            "parentStockFinanceId" => $request->get("parent_stock_finance_id"),
            "priceType" => $request->get("price_type"),
            "sellBuy" => 2,
            "stockCode" => $request->get("stock_code"),
            "stockFinanceId" => $request->get("id"),
        ];
        $ret = requestJava(self::ENTRUST_SELL_URL, [], $data);
        return isset($ret["code"]) && $ret["code"] ? parent::jsonReturn([], parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $ret["msg"] ?: "委托失败");
    }

    /**
     * 撤销委托卖出
     */
    public function cancelEntrustCell(Request $request)
    {
        $user = $request->user();
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1",
        ], [
            "委托信息错误",
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        if (!StockFinanceEntrust::where("cust_id", $user->id)->where("id", $request->get("id"))->count()) {
            return parent::jsonReturn([], parent::CODE_FAIL, "用户委托错误");
        }

        $ret = requestJava(self::CANCEL_ENTRUST_CELL_URL, ["entrustId" => $request->get("id")]);
        return isset($ret["code"]) && $ret["code"] ? parent::jsonReturn([], parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $ret["msg"] ?: "撤销失败");
    }

    /**
     * 撤销委托买入
     */
    public function cancelEntrustBuy(Request $request)
    {
        $user = $request->user();
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1",
        ], [
            "委托信息错误",
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        if (!StockFinanceEntrust::where("cust_id", $user->id)->where("id", $request->get("id"))->count()) {
            return parent::jsonReturn([], parent::CODE_FAIL, "用户委托错误");
        }

        $ret = requestJava(self::CANCEL_ENTRUST_BUY_URL, ["entrustId" => $request->get("id")]);
        return isset($ret["code"]) && $ret["code"] ? parent::jsonReturn([], parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $ret["msg"] ?: "撤销失败");
    }

    /**
     * 获得统计
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getCount(Request $request)
    {
        $user = $request->user();
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1"
        ], [
            "id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $ret = $this->transaction->getCount($user, $request->get("id"));
        return $ret ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, "查询错误");
    }

    /**
     * 获取子账户持仓列表
     * @param Request $request
     */
    public function getHoldingsList(Request $request)
    {
        $user = $request->user();
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1"
        ], [
            "id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }
        $ret = $this->transaction->getHoldingsList($user, $request->get("id"));
        return $ret ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, "查询错误");
    }

    /**
     * 获取用户股票池
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getStockPool(Request $request)
    {
        $pageSize = (int)($request->get("pageSize") ?: 10);
        $page = max($request->get("page"), 1);
        $ret = $this->transaction->getStockPool($request->user(), $page, $pageSize);
        return $ret !== false ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, "查询错误");
    }

    /**
     * 添加股票进股票池
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function addStockToPool(Request $request)
    {
        $validator = \Validator::make($request->all(), [
            "stock_code" => "required|numeric"
        ], [
            "请输入正确的证券代码"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $ret = $this->transaction->addStockToPool($request->user(), $request->get("stock_code"));
        return $ret ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $this->transaction->getErrorMsg() ?:
                "添加错误");
    }

    /**
     * 删除股票池股池
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function delStockFromPool(Request $request)
    {
        $validator = \Validator::make($request->all(), [
            "id" => "required|int|min:1"
        ], [
            "证券代码id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $ret = $this->transaction->delStockFromPool($request->user(), $request->get("id"));
        return $ret ? parent::jsonReturn([], parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $this->transaction->getErrorMsg() ?: "
            删除错误");
    }

    /**
     * 获取模糊搜索股票信息
     * @param Request $request
     */
    public function getStockList(Request $request)
    {
        $stockCode = $request->get("stock_code");
        if (strlen($stockCode) < 2) {
            return parent::jsonReturn([], parent::CODE_SUCCESS, "");
        }

        $data = getStockInfo($request->get("stock_code"));
        return parent::jsonReturn($data, parent::CODE_SUCCESS, "success");
    }

    /**
     * 准确搜索股票信息
     * @param Request $request
     */
    public function getStockInfo(Request $request)
    {
        $stockCode = $request->get("stock_code");
        if (strlen($stockCode) < 2) {
            return parent::jsonReturn([], parent::CODE_FAIL, "");
        }

        $data = getStockInfo($request->get("stock_code"), true);
        if ($data) {
            $data["s"] = $data["b"] = [];
            foreach ($data as $k => $v) {
                if (preg_match("/^b(\d)_([vp])$/", $k, $match)) {
                    if (isset($data["b"][$match[1]])) {
                        $data["b"][$match[1]][$match[2]] = $v;
                    } else {
                        $data["b"][$match[1]] = [$match[2] => $v, "id" => $match[1]];
                    }
                } else if (preg_match("/^a(\d)_([vp])$/", $k, $match)) {
                    if (isset($data["s"][$match[1]])) {
                        $data["s"][$match[1]][$match[2]] = $v;
                    } else {
                        $data["s"][$match[1]] = [$match[2] => $v, "id" => $match[1]];
                    }
                }
            }
            $data["s"] = array_reverse($data["s"]);
        }
        return $data ? parent::jsonReturn($data, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, "股票信息错误");
    }

    /**
     * 获取可撤单的委托
     * @param Request $request
     */
    public function getRevocableEntrustList(Request $request)
    {
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1"
        ], [
            "id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $ret = $this->transaction->getTodayEntrustList($request->user(), $request->get("id"),
            $entrustStatus = [1, 2], $custStatus = [2, 4]);
        return $ret ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $this->transaction->getErrorMsg() ?: "
            获取错误");
    }

    /**
     * 获取资金流水
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getDetails(Request $request)
    {
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1"
        ], [
            "id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $ret = $this->transaction->getDetails($request->user(), $request->get("id"));
        return $ret !== false ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, "data error");
    }

    /**
     * 获取当日委托
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getEntrustList(Request $request)
    {
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1"
        ], [
            "id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $ret = $this->transaction->getTodayEntrustList($request->user(), $request->get("id"),
            $entrustStatus = [], $custStatus = []);
        return $ret ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $this->transaction->getErrorMsg() ?: "
            获取错误");
    }

    /**
     * 获取历史委托
     * @param Request $request
     */
    public function getEntrustListHistory(Request $request)
    {
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1"
        ], [
            "id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $ret = $this->transaction->getEntrustListHistory($request->user(), $request->get("id"));
        return $ret ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $this->transaction->getErrorMsg() ?: "
            获取错误");
    }

    /**
     * 获取当日成交
     * @param Request $request
     */
    public function getMakedealList(Request $request)
    {
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1"
        ], [
            "id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $ret = $this->transaction->getMakedealList($request->user(), $request->get("id"), $isToday = true);
        return $ret ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $this->transaction->getErrorMsg() ?: "
            获取错误");
    }

    /**
     * 获取历史成交
     * @param Request $request
     */
    public function getMakedealListHistory(Request $request)
    {
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1"
        ], [
            "id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $ret = $this->transaction->getMakedealList($request->user(), $request->get("id"), $isToday = false);
        return $ret ? parent::jsonReturn($ret, parent::CODE_SUCCESS, "success") :
            parent::jsonReturn([], parent::CODE_FAIL, $this->transaction->getErrorMsg() ?: "
            获取错误");
    }

    /**
     * 获取最大可买股数
     * @param Request $request
     */
    public function getMaxStockNum(Request $request)
    {
        $user = $request->user();
        $validator = \Validator::make($request->all(), [
            "id" => "required|integer|min:1",
            "entrust_price" => "required|numeric|min:0.001"
        ], [
            "id错误"
        ]);

        if ($validator->fails()) {
            return parent::jsonReturn([], parent::CODE_FAIL, $validator->errors()->first());
        }

        $stockFinanceInfo = StockFinancing::where("id", $request->get("id"))->first();
        if (!$stockFinanceInfo) {
            return parent::jsonReturn([], parent::CODE_FAIL, "配资信息错误");
        }

        $agent = getAgent();
        $stockFeeInfo = \DB::table("s_stock_fees")->where("agent_id", $agent->id)->first();
        $rate = 0;
        if ($stockFeeInfo) {
            $rate = $stockFeeInfo->buy_commission_rate + $stockFeeInfo->buy_stampduty_rate + $stockFeeInfo->buy_transfer_rate
                + $stockFeeInfo->buy_witness_rate + $stockFeeInfo->buy_brokerage_rate + $stockFeeInfo->sell_fee_rate;
        }

        //最大可买股数：(可用余额 - 5)/ (1 + 手续费费率) / 委托价格
        //TODO 加入分控 持仓比例等
        $number = ($stockFinanceInfo->available_amount - 5) / (1 + $rate) / $request->get("entrust_price");
        $number = floor($number / 100) * 100;

        return parent::jsonReturn(["num" => $number], parent::CODE_SUCCESS, "");
    }
}
